﻿namespace Sai.Core
{
	using System;
	using System.Collections.Generic;
	using System.Collections.ObjectModel;
	using System.Linq;
	using Sai.Core.Introspection;
	using Sai.Core.Rules;

	public class TypeDifferenceWalker : IWalkTypeDifferences
	{
        private List<ITypeRule> typeValidationRules = new List<ITypeRule>();

        public void Walk(ITypeDeclaration was, ITypeDeclaration isNow, ITypeDifference typeDifference)
		{
            if ((was.Taxonomy == TypeTaxonomy.Class || was.Taxonomy == TypeTaxonomy.Interface)
                && (isNow.Taxonomy == TypeTaxonomy.Class || isNow.Taxonomy == TypeTaxonomy.Interface))
            {
                ReferenceTypeDeclaration wasAsRef = was as ReferenceTypeDeclaration;
                ReferenceTypeDeclaration isNowAsRef = isNow as ReferenceTypeDeclaration;

                var typeRules = this.typeValidationRules.OfType<IReferenceTypeRule>();

                foreach (var rule in typeRules)
                {
                    rule.Validate(wasAsRef, isNowAsRef, typeDifference);
                }
            }

            if (was.Taxonomy == TypeTaxonomy.Enum && isNow.Taxonomy == TypeTaxonomy.Enum)
            {
                EnumTypeDeclaration wasAsEnum = was as EnumTypeDeclaration;
                EnumTypeDeclaration isNowAsEnum = isNow as EnumTypeDeclaration;

                var enumRules = this.typeValidationRules.OfType<IEnumRule>();

                foreach (var rule in enumRules)
                {
                    rule.Validate(wasAsEnum, isNowAsEnum, typeDifference);
                }
            }

            if (was.Taxonomy == TypeTaxonomy.Class && isNow.Taxonomy == TypeTaxonomy.Class)
            {
                ClassDeclaration wasAsClass = was as ClassDeclaration;
                ClassDeclaration isNowAsClass = isNow as ClassDeclaration;

                var classRules = this.typeValidationRules.OfType<IClassRule>();

                foreach (var rule in classRules)
                {
                    rule.Validate(wasAsClass, isNowAsClass, typeDifference);
                }
            }

            if (was.Taxonomy == TypeTaxonomy.Interface && isNow.Taxonomy == TypeTaxonomy.Interface)
            {
                InterfaceDeclaration wasAsInterface = was as InterfaceDeclaration;
                InterfaceDeclaration isNowAsInterface = isNow as InterfaceDeclaration;
                
                var interfaceRules = this.typeValidationRules.OfType<IInterfaceRule>();

                foreach (var rule in interfaceRules)
                {
                    rule.Validate(wasAsInterface, isNowAsInterface, typeDifference);
                }
            }
		}

		public void Add(ITypeRule rule)
		{
			this.typeValidationRules.Add(rule);
		}
	}
}
